#include <iostream>
#include <vector>
#include <pthread.h>
#include "Thread.hpp"
#include "LockGuard.hpp"
#include <unistd.h>
using namespace ThreadModel;



//原版，有数据不一致问题
// void buytickets(ThreadData* td)
// {
//     while(true)
//     {
//         if(td->_tickets > 0)
//         {
//             usleep(1000);
//             printf("%s running, ticket : %d\n", td->_threadName.c_str(), td->_tickets);
//             td->_tickets--;
//             td->_total++;
//         }
//         else
//         {
//             break;
//         }
//     }
// }

// pthread_mutex_t gmutex = PTHREAD_MUTEX_INITIALIZER;
// //使用全局mutex上锁

// void buytickets(ThreadData* td)
// {
//     while(true)
//     {
//         pthread_mutex_lock(&gmutex);  //上锁
//         if(td->_tickets > 0)  //临界区
//         {
//             usleep(1000);
//             printf("%s running, ticket : %d\n", td->_threadName.c_str(), td->_tickets);
//             td->_tickets--; //临界区

//             pthread_mutex_unlock(&gmutex);

//             td->_total++;
//         }
//         else
//         {
//             pthread_mutex_unlock(&gmutex);

//             break;
//         }
//     }
// }

//局部封装mutex
class ThreadData
{
public:
    ThreadData(pthread_mutex_t& mutex, int& tickets, const std::string& name)
        :_mutex(mutex), _tickets(tickets), _threadName(name), _total(0)
    {
    }
    ~ThreadData()
    {}
public:
    pthread_mutex_t& _mutex;
    int& _tickets;
    std::string _threadName;
    int _total;
};

const int NUM = 4;
int g_ticket = 10000;

void buytickets(ThreadData* td)
{
    while(true)
    {
        // pthread_mutex_lock(&td->_mutex);  //上锁
        // if(td->_tickets > 0)  //临界区
        // {
        //     usleep(1000);
        //     printf("%s running, ticket : %d\n", td->_threadName.c_str(), td->_tickets);
        //     td->_tickets--; //临界区

        //     pthread_mutex_unlock(&td->_mutex);

        //     td->_total++;
        // }
        // else
        // {
        //     pthread_mutex_unlock(&td->_mutex);

        //     break;
        // }

        //RAII + mutex
        LockGuard lg(&td->_mutex);
        if(td->_tickets > 0)
        {
            usleep(1000);
            printf("%s running, ticket : %d\n", td->_threadName.c_str(), td->_tickets);
            td->_tickets--;

            td->_total++; 
        }
        else
        {
            break;
        }
    }
}

int main()
{
    pthread_mutex_t mutex;
    pthread_mutex_init(&mutex, nullptr);
    std::vector<Thread<ThreadData*>> threads;
    std::vector<ThreadData*> datas;

    //创建线程
    for (int i = 0; i < NUM; i++)
    {
        std::string name = "thread-" + std::to_string(i + 1);
        ThreadData* td = new ThreadData(mutex, g_ticket, name);
        threads.emplace_back(buytickets, td, name);
        datas.emplace_back(td);
    }

    //开始执行
    std::cout << "start running ..." << std::endl;
    for (auto thread : threads)
    {
        thread.Start();
    }
    //等待线程
    //sleep(1000);
    for (auto thread : threads)
    {
        thread.Join();
    }
    //获取结果数据
    sleep(12);
    pthread_mutex_destroy(&mutex);
    for (auto data : datas)
    {
        printf("%s : %d\n", data->_threadName.c_str(), data->_total);
        delete data;
    }
    return 0;
}